home *** CD-ROM | disk | FTP | other *** search
/ Aminet 49 / Aminet 49 (2002)(GTI - Schatztruhe)[!][Jun 2002].iso / Aminet / util / libs / ttrender.lha / ttrender-2.0 / Developer / source / smooth / ftgrays.c next >
Encoding:
C/C++ Source or Header  |  2002-04-06  |  56.2 KB  |  2,142 lines

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ftgrays.c                                                              */
  4. /*                                                                         */
  5. /*    A new `perfect' anti-aliasing renderer (body).                       */
  6. /*                                                                         */
  7. /*  Copyright 2000-2001 by                                                 */
  8. /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  9. /*                                                                         */
  10. /*  This file is part of the FreeType project, and may only be used,       */
  11. /*  modified, and distributed under the terms of the FreeType project      */
  12. /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  13. /*  this file you indicate that you have read the license and              */
  14. /*  understand and accept it fully.                                        */
  15. /*                                                                         */
  16. /***************************************************************************/
  17.  
  18.   /*************************************************************************/
  19.   /*                                                                       */
  20.   /*  This file can be compiled without the rest of the FreeType engine,   */
  21.   /*  by defining the _STANDALONE_ macro when compiling it.  You also need */
  22.   /*  to put the files `ftgrays.h' and `ftimage.h' into the current        */
  23.   /*  compilation directory.  Typically, you could do something like       */
  24.   /*                                                                       */
  25.   /*  - copy `src/base/ftgrays.c' to your current directory                */
  26.   /*                                                                       */
  27.   /*  - copy `include/freetype/ftimage.h' and                              */
  28.   /*    `include/freetype/ftgrays.h' to the same directory                 */
  29.   /*                                                                       */
  30.   /*  - compile `ftgrays' with the _STANDALONE_ macro defined, as in       */
  31.   /*                                                                       */
  32.   /*      cc -c -D_STANDALONE_ ftgrays.c                                   */
  33.   /*                                                                       */
  34.   /*  The renderer can be initialized with a call to                       */
  35.   /*  `ft_gray_raster.gray_raster_new'; an anti-aliased bitmap can be      */
  36.   /*  generated with a call to `ft_gray_raster.gray_raster_render'.        */
  37.   /*                                                                       */
  38.   /*  See the comments and documentation in the file `ftimage.h' for       */
  39.   /*  more details on how the raster works.                                */
  40.   /*                                                                       */
  41.   /*************************************************************************/
  42.  
  43.   /*************************************************************************/
  44.   /*                                                                       */
  45.   /*  This is a new anti-aliasing scan-converter for FreeType 2.  The      */
  46.   /*  algorithm used here is _very_ different from the one in the standard */
  47.   /*  `ftraster' module.  Actually, `ftgrays' computes the _exact_         */
  48.   /*  coverage of the outline on each pixel cell.                          */
  49.   /*                                                                       */
  50.   /*  It is based on ideas that I initially found in Raph Levien's         */
  51.   /*  excellent LibArt graphics library (see http://www.levien.com/libart  */
  52.   /*  for more information, though the web pages do not tell anything      */
  53.   /*  about the renderer; you'll have to dive into the source code to      */
  54.   /*  understand how it works).                                            */
  55.   /*                                                                       */
  56.   /*  Note, however, that this is a _very_ different implementation        */
  57.   /*  compared to Raph's.  Coverage information is stored in a very        */
  58.   /*  different way, and I don't use sorted vector paths.  Also, it        */
  59.   /*  doesn't use floating point values.                                   */
  60.   /*                                                                       */
  61.   /*  This renderer has the following advantages:                          */
  62.   /*                                                                       */
  63.   /*  - It doesn't need an intermediate bitmap.  Instead, one can supply   */
  64.   /*    a callback function that will be called by the renderer to draw    */
  65.   /*    gray spans on any target surface.  You can thus do direct          */
  66.   /*    composition on any kind of bitmap, provided that you give the      */
  67.   /*    renderer the right callback.                                       */
  68.   /*                                                                       */
  69.   /*  - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on  */
  70.   /*    each pixel cell                                                    */
  71.   /*                                                                       */
  72.   /*  - It performs a single pass on the outline (the `standard' FT2       */
  73.   /*    renderer makes two passes).                                        */
  74.   /*                                                                       */
  75.   /*  - It can easily be modified to render to _any_ number of gray levels */
  76.   /*    cheaply.                                                           */
  77.   /*                                                                       */
  78.   /*  - For small (< 20) pixel sizes, it is faster than the standard       */
  79.   /*    renderer.                                                          */
  80.   /*                                                                       */
  81.   /*************************************************************************/
  82.  
  83.  
  84. #include <string.h>             /* for memcpy() */
  85. #include <setjmp.h>
  86.  
  87.  
  88. /* experimental support for gamma correction within the rasterizer */
  89. #define xxxGRAYS_USE_GAMMA
  90.  
  91.  
  92.   /*************************************************************************/
  93.   /*                                                                       */
  94.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  95.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  96.   /* messages during execution.                                            */
  97.   /*                                                                       */
  98. #undef  FT_COMPONENT
  99. #define FT_COMPONENT  trace_aaraster
  100.  
  101.  
  102. #define ErrRaster_MemoryOverflow   -4
  103.  
  104. #ifdef _STANDALONE_
  105.  
  106.  
  107. #define ErrRaster_Invalid_Mode     -2
  108. #define ErrRaster_Invalid_Outline  -1
  109.  
  110. #include "ftimage.h"
  111. #include "ftgrays.h"
  112.  
  113.   /* This macro is used to indicate that a function parameter is unused. */
  114.   /* Its purpose is simply to reduce compiler warnings.  Note also that  */
  115.   /* simply defining it as `(void)x' doesn't avoid warnings with certain */
  116.   /* ANSI compilers (e.g. LCC).                                          */
  117. #define FT_UNUSED( x )  (x) = (x)
  118.  
  119.   /* Disable the tracing mechanism for simplicity -- developers can      */
  120.   /* activate it easily by redefining these two macros.                  */
  121. #ifndef FT_ERROR
  122. #define FT_ERROR( x )  do ; while ( 0 )     /* nothing */
  123. #endif
  124.  
  125. #ifndef FT_TRACE
  126. #define FT_TRACE( x )  do ; while ( 0 )     /* nothing */
  127. #endif
  128.  
  129.  
  130. #else /* _STANDALONE_ */
  131.  
  132.  
  133. #include <ft2build.h>
  134. #include "ftgrays.h"
  135. #include FT_INTERNAL_OBJECTS_H
  136. #include FT_INTERNAL_DEBUG_H
  137. #include FT_OUTLINE_H
  138.  
  139. #include "ftsmerrs.h"
  140.  
  141. #define ErrRaster_Invalid_Mode     Smooth_Err_Cannot_Render_Glyph
  142. #define ErrRaster_Invalid_Outline  Smooth_Err_Invalid_Outline
  143.  
  144.  
  145. #endif /* _STANDALONE_ */
  146.  
  147.  
  148. #ifndef MEM_Set
  149. #define  MEM_Set( d, s, c )  memset( d, s, c )
  150. #endif
  151.  
  152.   /* define this to dump debugging information */
  153. #define xxxDEBUG_GRAYS
  154.  
  155.   /* as usual, for the speed hungry :-) */
  156.  
  157. #ifndef FT_STATIC_RASTER
  158.  
  159.  
  160. #define RAS_ARG   PRaster  raster
  161. #define RAS_ARG_  PRaster  raster,
  162.  
  163. #define RAS_VAR   raster
  164. #define RAS_VAR_  raster,
  165.  
  166. #define ras       (*raster)
  167.  
  168.  
  169. #else /* FT_STATIC_RASTER */
  170.  
  171.  
  172. #define RAS_ARG   /* empty */
  173. #define RAS_ARG_  /* empty */
  174. #define RAS_VAR   /* empty */
  175. #define RAS_VAR_  /* empty */
  176.  
  177.   static TRaster  ras;
  178.  
  179.  
  180. #endif /* FT_STATIC_RASTER */
  181.  
  182.  
  183.   /* must be at least 6 bits! */
  184. #define PIXEL_BITS  8
  185.  
  186. #define ONE_PIXEL       ( 1L << PIXEL_BITS )
  187. #define PIXEL_MASK      ( -1L << PIXEL_BITS )
  188. #define TRUNC( x )      ( (x) >> PIXEL_BITS )
  189. #define SUBPIXELS( x )  ( (x) << PIXEL_BITS )
  190. #define FLOOR( x )      ( (x) & -ONE_PIXEL )
  191. #define CEILING( x )    ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL )
  192. #define ROUND( x )      ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL )
  193.  
  194. #if PIXEL_BITS >= 6
  195. #define UPSCALE( x )    ( (x) << ( PIXEL_BITS - 6 ) )
  196. #define DOWNSCALE( x )  ( (x) >> ( PIXEL_BITS - 6 ) )
  197. #else
  198. #define UPSCALE( x )    ( (x) >> ( 6 - PIXEL_BITS ) )
  199. #define DOWNSCALE( x )  ( (x) << ( 6 - PIXEL_BITS ) )
  200. #endif
  201.  
  202.   /* Define this if you want to use a more compact storage scheme.  This   */
  203.   /* increases the number of cells available in the render pool but slows  */
  204.   /* down the rendering a bit.  It is useful if you have a really tiny     */
  205.   /* render pool.                                                          */
  206. #define xxxGRAYS_COMPACT
  207.  
  208.  
  209.   /*************************************************************************/
  210.   /*                                                                       */
  211.   /*   TYPE DEFINITIONS                                                    */
  212.   /*                                                                       */
  213.  
  214.   /* don't change the following types to FT_Int or FT_Pos, since we might */
  215.   /* need to define them to "float" or "double" when experimenting with   */
  216.   /* new algorithms                                                       */
  217.  
  218.   typedef int   TScan;   /* integer scanline/pixel coordinate */
  219.   typedef long  TPos;    /* sub-pixel coordinate              */
  220.  
  221.   /* determine the type used to store cell areas.  This normally takes at */
  222.   /* least PIXEL_BYTES*2 + 1.  On 16-bit systems, we need to use `long'   */
  223.   /* instead of `int', otherwise bad things happen                        */
  224.  
  225. #if PIXEL_BITS <= 7
  226.  
  227.   typedef int   TArea;
  228.  
  229. #else /* PIXEL_BITS >= 8 */
  230.  
  231.   /* approximately determine the size of integers using an ANSI-C header */
  232. #include <limits.h>
  233.  
  234. #if UINT_MAX == 0xFFFFU
  235.   typedef long  TArea;
  236. #else
  237.   typedef int  TArea;
  238. #endif
  239.  
  240. #endif /* PIXEL_BITS >= 8 */
  241.  
  242.  
  243.   /* maximal number of gray spans in a call to the span callback */
  244. #define FT_MAX_GRAY_SPANS  32
  245.  
  246.  
  247. #ifdef GRAYS_COMPACT
  248.  
  249.   typedef struct  TCell_
  250.   {
  251.     short  x     : 14;
  252.     short  y     : 14;
  253.     int    cover : PIXEL_BITS + 2;
  254.     int    area  : PIXEL_BITS * 2 + 2;
  255.  
  256.   } TCell, *PCell;
  257.  
  258. #else /* GRAYS_COMPACT */
  259.  
  260.   typedef struct  TCell_
  261.   {
  262.     TScan  x;
  263.     TScan  y;
  264.     int    cover;
  265.     TArea  area;
  266.  
  267.   } TCell, *PCell;
  268.  
  269. #endif /* GRAYS_COMPACT */
  270.  
  271.  
  272.   typedef struct  TRaster_
  273.   {
  274.     PCell  cells;
  275.     int    max_cells;
  276.     int    num_cells;
  277.  
  278.     TScan  min_ex, max_ex;
  279.     TScan  min_ey, max_ey;
  280.  
  281.     TArea  area;
  282.     int    cover;
  283.     int    invalid;
  284.  
  285.     TScan  ex, ey;
  286.     TScan  cx, cy;
  287.     TPos   x,  y;
  288.  
  289.     TScan  last_ey;
  290.  
  291.     FT_Vector   bez_stack[32 * 3 + 1];
  292.     int         lev_stack[32];
  293.  
  294.     FT_Outline  outline;
  295.     FT_Bitmap   target;
  296.     FT_BBox     clip_box;
  297.  
  298.     FT_Span     gray_spans[FT_MAX_GRAY_SPANS];
  299.     int         num_gray_spans;
  300.  
  301.     FT_Raster_Span_Func  render_span;
  302.     void*                render_span_data;
  303.     int                  span_y;
  304.  
  305.     int  band_size;
  306.     int  band_shoot;
  307.     int  conic_level;
  308.     int  cubic_level;
  309.  
  310.     void*    memory;
  311.     jmp_buf  jump_buffer;
  312.  
  313. #ifdef GRAYS_USE_GAMMA
  314.     FT_Byte  gamma[257];
  315. #endif
  316.  
  317.   } TRaster, *PRaster;
  318.  
  319.  
  320.   /*************************************************************************/
  321.   /*                                                                       */
  322.   /* Initialize the cells table.                                           */
  323.   /*                                                                       */
  324.   static void
  325.   gray_init_cells( RAS_ARG_ void*  buffer,
  326.                    long            byte_size )
  327.   {
  328.     ras.cells     = (PCell)buffer;
  329.     ras.max_cells = byte_size / sizeof ( TCell );
  330.     ras.num_cells = 0;
  331.     ras.area      = 0;
  332.     ras.cover     = 0;
  333.     ras.invalid   = 1;
  334.   }
  335.  
  336.  
  337.   /*************************************************************************/
  338.   /*                                                                       */
  339.   /* Compute the outline bounding box.                                     */
  340.   /*                                                                       */
  341.   static void
  342.   gray_compute_cbox( RAS_ARG )
  343.   {
  344.     FT_Outline*  outline = &ras.outline;
  345.     FT_Vector*   vec     = outline->points;
  346.     FT_Vector*   limit   = vec + outline->n_points;
  347.  
  348.  
  349.     if ( outline->n_points <= 0 )
  350.     {
  351.       ras.min_ex = ras.max_ex = 0;
  352.       ras.min_ey = ras.max_ey = 0;
  353.       return;
  354.     }
  355.  
  356.     ras.min_ex = ras.max_ex = vec->x;
  357.     ras.min_ey = ras.max_ey = vec->y;
  358.  
  359.     vec++;
  360.  
  361.     for ( ; vec < limit; vec++ )
  362.     {
  363.       TPos  x = vec->x;
  364.       TPos  y = vec->y;
  365.  
  366.  
  367.       if ( x < ras.min_ex ) ras.min_ex = x;
  368.       if ( x > ras.max_ex ) ras.max_ex = x;
  369.       if ( y < ras.min_ey ) ras.min_ey = y;
  370.       if ( y > ras.max_ey ) ras.max_ey = y;
  371.     }
  372.  
  373.     /* truncate the bounding box to integer pixels */
  374.     ras.min_ex = ras.min_ex >> 6;
  375.     ras.min_ey = ras.min_ey >> 6;
  376.     ras.max_ex = ( ras.max_ex + 63 ) >> 6;
  377.     ras.max_ey = ( ras.max_ey + 63 ) >> 6;
  378.   }
  379.  
  380.  
  381.   /*************************************************************************/
  382.   /*                                                                       */
  383.   /* Record the current cell in the table.                                 */
  384.   /*                                                                       */
  385.   static void
  386.   gray_record_cell( RAS_ARG )
  387.   {
  388.     PCell  cell;
  389.  
  390.  
  391.     if ( !ras.invalid && ( ras.area | ras.cover ) )
  392.     {
  393.       if ( ras.num_cells >= ras.max_cells )
  394.         longjmp( ras.jump_buffer, 1 );
  395.  
  396.       cell        = ras.cells + ras.num_cells++;
  397.       cell->x     = ras.ex - ras.min_ex;
  398.       cell->y     = ras.ey - ras.min_ey;
  399.       cell->area  = ras.area;
  400.       cell->cover = ras.cover;
  401.     }
  402.   }
  403.  
  404.  
  405.   /*************************************************************************/
  406.   /*                                                                       */
  407.   /* Set the current cell to a new position.                               */
  408.   /*                                                                       */
  409.   static void
  410.   gray_set_cell( RAS_ARG_ TScan  ex,
  411.                           TScan  ey )
  412.   {
  413.     int  invalid, record, clean;
  414.  
  415.  
  416.     /* Move the cell pointer to a new position.  We set the `invalid'      */
  417.     /* flag to indicate that the cell isn't part of those we're interested */
  418.     /* in during the render phase.  This means that:                       */
  419.     /*                                                                     */
  420.     /* . the new vertical position must be within min_ey..max_ey-1.        */
  421.     /* . the new horizontal position must be strictly less than max_ex     */
  422.     /*                                                                     */
  423.     /* Note that if a cell is to the left of the clipping region, it is    */
  424.     /* actually set to the (min_ex-1) horizontal position.                 */
  425.  
  426.     record  = 0;
  427.     clean   = 1;
  428.  
  429.     invalid = ( ey < ras.min_ey || ey >= ras.max_ey || ex >= ras.max_ex );
  430.     if ( !invalid )
  431.     {
  432.       /* All cells that are on the left of the clipping region go to the */
  433.       /* min_ex - 1 horizontal position.                                 */
  434.       if ( ex < ras.min_ex )
  435.         ex = ras.min_ex - 1;
  436.  
  437.       /* if our position is new, then record the previous cell */
  438.       if ( ex != ras.ex || ey != ras.ey )
  439.         record = 1;
  440.       else
  441.         clean = ras.invalid;  /* do not clean if we didn't move from */
  442.                               /* a valid cell                        */
  443.     }
  444.  
  445.     /* record the previous cell if needed (i.e., if we changed the cell */
  446.     /* position, of changed the `invalid' flag)                         */
  447.     if ( ras.invalid != invalid || record )
  448.       gray_record_cell( RAS_VAR );
  449.  
  450.     if ( clean )
  451.     {
  452.       ras.area  = 0;
  453.       ras.cover = 0;
  454.     }
  455.  
  456.     ras.invalid = invalid;
  457.     ras.ex      = ex;
  458.     ras.ey      = ey;
  459.   }
  460.  
  461.  
  462.   /*************************************************************************/
  463.   /*                                                                       */
  464.   /* Start a new contour at a given cell.                                  */
  465.   /*                                                                       */
  466.   static void
  467.   gray_start_cell( RAS_ARG_  TScan  ex,
  468.                              TScan  ey )
  469.   {
  470.     if ( ex < ras.min_ex )
  471.       ex = ras.min_ex - 1;
  472.  
  473.     ras.area    = 0;
  474.     ras.cover   = 0;
  475.     ras.ex      = ex;
  476.     ras.ey      = ey;
  477.     ras.last_ey = SUBPIXELS( ey );
  478.     ras.invalid = 0;
  479.  
  480.     gray_set_cell( RAS_VAR_ ex, ey );
  481.   }
  482.  
  483.  
  484.   /*************************************************************************/
  485.   /*                                                                       */
  486.   /* Render a scanline as one or more cells.                               */
  487.   /*                                                                       */
  488.   static void
  489.   gray_render_scanline( RAS_ARG_  TScan  ey,
  490.                                   TPos   x1,
  491.                                   TScan  y1,
  492.                                   TPos   x2,
  493.                                   TScan  y2 )
  494.   {
  495.     TScan  ex1, ex2, fx1, fx2, delta;
  496.     long   p, first, dx;
  497.     int    incr, lift, mod, rem;
  498.  
  499.  
  500.     dx = x2 - x1;
  501.  
  502.     ex1 = TRUNC( x1 ); /* if (ex1 >= ras.max_ex) ex1 = ras.max_ex-1; */
  503.     ex2 = TRUNC( x2 ); /* if (ex2 >= ras.max_ex) ex2 = ras.max_ex-1; */
  504.     fx1 = x1 - SUBPIXELS( ex1 );
  505.     fx2 = x2 - SUBPIXELS( ex2 );
  506.  
  507.     /* trivial case.  Happens often */
  508.     if ( y1 == y2 )
  509.     {
  510.       gray_set_cell( RAS_VAR_ ex2, ey );
  511.       return;
  512.     }
  513.  
  514.     /* everything is located in a single cell.  That is easy! */
  515.     /*                                                        */
  516.     if ( ex1 == ex2 )
  517.     {
  518.       delta      = y2 - y1;
  519.       ras.area  += (TArea)( fx1 + fx2 ) * delta;
  520.       ras.cover += delta;
  521.       return;
  522.     }
  523.  
  524.     /* ok, we'll have to render a run of adjacent cells on the same */
  525.     /* scanline...                                                  */
  526.     /*                                                              */
  527.     p     = ( ONE_PIXEL - fx1 ) * ( y2 - y1 );
  528.     first = ONE_PIXEL;
  529.     incr  = 1;
  530.  
  531.     if ( dx < 0 )
  532.     {
  533.       p     = fx1 * ( y2 - y1 );
  534.       first = 0;
  535.       incr  = -1;
  536.       dx    = -dx;
  537.     }
  538.  
  539.     delta = p / dx;
  540.     mod   = p % dx;
  541.     if ( mod < 0 )
  542.     {
  543.       delta--;
  544.       mod += dx;
  545.     }
  546.  
  547.     ras.area  += (TArea)( fx1 + first ) * delta;
  548.     ras.cover += delta;
  549.  
  550.     ex1 += incr;
  551.     gray_set_cell( RAS_VAR_ ex1, ey );
  552.     y1  += delta;
  553.  
  554.     if ( ex1 != ex2 )
  555.     {
  556.       p     = ONE_PIXEL * ( y2 - y1 + delta );
  557.       lift  = p / dx;
  558.       rem   = p % dx;
  559.       if ( rem < 0 )
  560.       {
  561.         lift--;
  562.         rem += dx;
  563.       }
  564.  
  565.       mod -= dx;
  566.  
  567.       while ( ex1 != ex2 )
  568.       {
  569.         delta = lift;
  570.         mod  += rem;
  571.         if ( mod >= 0 )
  572.         {
  573.           mod -= dx;
  574.           delta++;
  575.         }
  576.  
  577.         ras.area  += (TArea)ONE_PIXEL * delta;
  578.         ras.cover += delta;
  579.         y1        += delta;
  580.         ex1       += incr;
  581.         gray_set_cell( RAS_VAR_ ex1, ey );
  582.       }
  583.     }
  584.  
  585.     delta      = y2 - y1;
  586.     ras.area  += (TArea)( fx2 + ONE_PIXEL - first ) * delta;
  587.     ras.cover += delta;
  588.   }
  589.  
  590.  
  591.   /*************************************************************************/
  592.   /*                                                                       */
  593.   /* Render a given line as a series of scanlines.                         */
  594.   /*                                                                       */
  595.   static void
  596.   gray_render_line( RAS_ARG_ TPos  to_x,
  597.                              TPos  to_y )
  598.   {
  599.     TScan  ey1, ey2, fy1, fy2;
  600.     TPos   dx, dy, x, x2;
  601.     int    p, rem, mod, lift, delta, first, incr;
  602.  
  603.  
  604.     ey1 = TRUNC( ras.last_ey );
  605.     ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
  606.     fy1 = ras.y - ras.last_ey;
  607.     fy2 = to_y - SUBPIXELS( ey2 );
  608.  
  609.     dx = to_x - ras.x;
  610.     dy = to_y - ras.y;
  611.  
  612.     /* XXX: we should do something about the trivial case where dx == 0, */
  613.     /*      as it happens very often!                                    */
  614.  
  615.     /* perform vertical clipping */
  616.     {
  617.       TScan  min, max;
  618.  
  619.  
  620.       min = ey1;
  621.       max = ey2;
  622.       if ( ey1 > ey2 )
  623.       {
  624.         min = ey2;
  625.         max = ey1;
  626.       }
  627.       if ( min >= ras.max_ey || max < ras.min_ey )
  628.         goto End;
  629.     }
  630.  
  631.     /* everything is on a single scanline */
  632.     if ( ey1 == ey2 )
  633.     {
  634.       gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 );
  635.       goto End;
  636.     }
  637.  
  638.     /* vertical line - avoid calling gray_render_scanline */
  639.     incr = 1;
  640.  
  641.     if ( dx == 0 )
  642.     {
  643.       TScan  ex     = TRUNC( ras.x );
  644.       TScan  two_fx = ( ras.x - SUBPIXELS( ex ) ) << 1;
  645.       TPos   area;
  646.  
  647.  
  648.       first = ONE_PIXEL;
  649.       if ( dy < 0 )
  650.       {
  651.         first = 0;
  652.         incr  = -1;
  653.       }
  654.  
  655.       delta      = first - fy1;
  656.       ras.area  += (TArea)two_fx * delta;
  657.       ras.cover += delta;
  658.       ey1       += incr;
  659.  
  660.       gray_set_cell( raster, ex, ey1 );
  661.  
  662.       delta = first + first - ONE_PIXEL;
  663.       area  = (TArea)two_fx * delta;
  664.       while( ey1 != ey2 )
  665.       {
  666.         ras.area  += area;
  667.         ras.cover += delta;
  668.         ey1       += incr;
  669.         gray_set_cell( raster, ex, ey1 );
  670.       }
  671.  
  672.       delta      = fy2 - ONE_PIXEL + first;
  673.       ras.area  += (TArea)two_fx * delta;
  674.       ras.cover += delta;
  675.       goto End;
  676.     }
  677.  
  678.     /* ok, we have to render several scanlines */
  679.     p     = ( ONE_PIXEL - fy1 ) * dx;
  680.     first = ONE_PIXEL;
  681.     incr  = 1;
  682.  
  683.     if ( dy < 0 )
  684.     {
  685.       p     = fy1 * dx;
  686.       first = 0;
  687.       incr  = -1;
  688.       dy    = -dy;
  689.     }
  690.  
  691.     delta = p / dy;
  692.     mod   = p % dy;
  693.     if ( mod < 0 )
  694.     {
  695.       delta--;
  696.       mod += dy;
  697.     }
  698.  
  699.     x = ras.x + delta;
  700.     gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, first );
  701.  
  702.     ey1 += incr;
  703.     gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
  704.  
  705.     if ( ey1 != ey2 )
  706.     {
  707.       p     = ONE_PIXEL * dx;
  708.       lift  = p / dy;
  709.       rem   = p % dy;
  710.       if ( rem < 0 )
  711.       {
  712.         lift--;
  713.         rem += dy;
  714.       }
  715.       mod -= dy;
  716.  
  717.       while ( ey1 != ey2 )
  718.       {
  719.         delta = lift;
  720.         mod  += rem;
  721.         if ( mod >= 0 )
  722.         {
  723.           mod -= dy;
  724.           delta++;
  725.         }
  726.  
  727.         x2 = x + delta;
  728.         gray_render_scanline( RAS_VAR_ ey1, x, ONE_PIXEL - first, x2, first );
  729.         x = x2;
  730.  
  731.         ey1 += incr;
  732.         gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
  733.       }
  734.     }
  735.  
  736.     gray_render_scanline( RAS_VAR_ ey1, x, ONE_PIXEL - first, to_x, fy2 );
  737.  
  738.   End:
  739.     ras.x       = to_x;
  740.     ras.y       = to_y;
  741.     ras.last_ey = SUBPIXELS( ey2 );
  742.   }
  743.  
  744.  
  745.   static void
  746.   gray_split_conic( FT_Vector*  base )
  747.   {
  748.     TPos  a, b;
  749.  
  750.  
  751.     base[4].x = base[2].x;
  752.     b = base[1].x;
  753.     a = base[3].x = ( base[2].x + b ) / 2;
  754.     b = base[1].x = ( base[0].x + b ) / 2;
  755.     base[2].x = ( a + b ) / 2;
  756.  
  757.     base[4].y = base[2].y;
  758.     b = base[1].y;
  759.     a = base[3].y = ( base[2].y + b ) / 2;
  760.     b = base[1].y = ( base[0].y + b ) / 2;
  761.     base[2].y = ( a + b ) / 2;
  762.   }
  763.  
  764.  
  765.   static void
  766.   gray_render_conic( RAS_ARG_ FT_Vector*  control,
  767.                               FT_Vector*  to )
  768.   {
  769.     TPos        dx, dy;
  770.     int         top, level;
  771.     int*        levels;
  772.     FT_Vector*  arc;
  773.  
  774.  
  775.     dx = DOWNSCALE( ras.x ) + to->x - ( control->x << 1 );
  776.     if ( dx < 0 )
  777.       dx = -dx;
  778.     dy = DOWNSCALE( ras.y ) + to->y - ( control->y << 1 );
  779.     if ( dy < 0 )
  780.       dy = -dy;
  781.     if ( dx < dy )
  782.       dx = dy;
  783.  
  784.     level = 1;
  785.     dx = dx / ras.conic_level;
  786.     while ( dx > 0 )
  787.     {
  788.       dx >>= 2;
  789.       level++;
  790.     }
  791.  
  792.     /* a shortcut to speed things up */
  793.     if ( level <= 1 )
  794.     {
  795.       /* we compute the mid-point directly in order to avoid */
  796.       /* calling gray_split_conic()                          */
  797.       TPos   to_x, to_y, mid_x, mid_y;
  798.  
  799.  
  800.       to_x  = UPSCALE( to->x );
  801.       to_y  = UPSCALE( to->y );
  802.       mid_x = ( ras.x + to_x + 2 * UPSCALE( control->x ) ) / 4;
  803.       mid_y = ( ras.y + to_y + 2 * UPSCALE( control->y ) ) / 4;
  804.  
  805.       gray_render_line( RAS_VAR_ mid_x, mid_y );
  806.       gray_render_line( RAS_VAR_ to_x, to_y );
  807.       return;
  808.     }
  809.  
  810.     arc       = ras.bez_stack;
  811.     levels    = ras.lev_stack;
  812.     top       = 0;
  813.     levels[0] = level;
  814.  
  815.     arc[0].x = UPSCALE( to->x );
  816.     arc[0].y = UPSCALE( to->y );
  817.     arc[1].x = UPSCALE( control->x );
  818.     arc[1].y = UPSCALE( control->y );
  819.     arc[2].x = ras.x;
  820.     arc[2].y = ras.y;
  821.  
  822.     while ( top >= 0 )
  823.     {
  824.       level = levels[top];
  825.       if ( level > 1 )
  826.       {
  827.         /* check that the arc crosses the current band */
  828.         TPos  min, max, y;
  829.  
  830.  
  831.         min = max = arc[0].y;
  832.  
  833.         y = arc[1].y;
  834.         if ( y < min ) min = y;
  835.         if ( y > max ) max = y;
  836.  
  837.         y = arc[2].y;
  838.         if ( y < min ) min = y;
  839.         if ( y > max ) max = y;
  840.  
  841.         if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
  842.           goto Draw;
  843.  
  844.         gray_split_conic( arc );
  845.         arc += 2;
  846.         top++;
  847.         levels[top] = levels[top - 1] = level - 1;
  848.         continue;
  849.       }
  850.  
  851.     Draw:
  852.       {
  853.         TPos  to_x, to_y, mid_x, mid_y;
  854.  
  855.  
  856.         to_x  = arc[0].x;
  857.         to_y  = arc[0].y;
  858.         mid_x = ( ras.x + to_x + 2 * arc[1].x ) / 4;
  859.         mid_y = ( ras.y + to_y + 2 * arc[1].y ) / 4;
  860.  
  861.         gray_render_line( RAS_VAR_ mid_x, mid_y );
  862.         gray_render_line( RAS_VAR_ to_x, to_y );
  863.  
  864.         top--;
  865.         arc -= 2;
  866.       }
  867.     }
  868.     return;
  869.   }
  870.  
  871.  
  872.   static void
  873.   gray_split_cubic( FT_Vector*  base )
  874.   {
  875.     TPos  a, b, c, d;
  876.  
  877.  
  878.     base[6].x = base[3].x;
  879.     c = base[1].x;
  880.     d = base[2].x;
  881.     base[1].x = a = ( base[0].x + c ) / 2;
  882.     base[5].x = b = ( base[3].x + d ) / 2;
  883.     c = ( c + d ) / 2;
  884.     base[2].x = a = ( a + c ) / 2;
  885.     base[4].x = b = ( b + c ) / 2;
  886.     base[3].x = ( a + b ) / 2;
  887.  
  888.     base[6].y = base[3].y;
  889.     c = base[1].y;
  890.     d = base[2].y;
  891.     base[1].y = a = ( base[0].y + c ) / 2;
  892.     base[5].y = b = ( base[3].y + d ) / 2;
  893.     c = ( c + d ) / 2;
  894.     base[2].y = a = ( a + c ) / 2;
  895.     base[4].y = b = ( b + c ) / 2;
  896.     base[3].y = ( a + b ) / 2;
  897.   }
  898.  
  899.  
  900.   static void
  901.   gray_render_cubic( RAS_ARG_ FT_Vector*  control1,
  902.                               FT_Vector*  control2,
  903.                               FT_Vector*  to )
  904.   {
  905.     TPos        dx, dy, da, db;
  906.     int         top, level;
  907.     int*        levels;
  908.     FT_Vector*  arc;
  909.  
  910.  
  911.     dx = DOWNSCALE( ras.x ) + to->x - ( control1->x << 1 );
  912.     if ( dx < 0 )
  913.       dx = -dx;
  914.     dy = DOWNSCALE( ras.y ) + to->y - ( control1->y << 1 );
  915.     if ( dy < 0 )
  916.       dy = -dy;
  917.     if ( dx < dy )
  918.       dx = dy;
  919.     da = dx;
  920.  
  921.     dx = DOWNSCALE( ras.x ) + to->x - 3 * ( control1->x + control2->x );
  922.     if ( dx < 0 )
  923.       dx = -dx;
  924.     dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->x + control2->y );
  925.     if ( dy < 0 )
  926.       dy = -dy;
  927.     if ( dx < dy )
  928.       dx = dy;
  929.     db = dx;
  930.  
  931.     level = 1;
  932.     da    = da / ras.cubic_level;
  933.     db    = db / ras.conic_level;
  934.     while ( da > 0 || db > 0 )
  935.     {
  936.       da >>= 2;
  937.       db >>= 3;
  938.       level++;
  939.     }
  940.  
  941.     if ( level <= 1 )
  942.     {
  943.       TPos   to_x, to_y, mid_x, mid_y;
  944.  
  945.  
  946.       to_x  = UPSCALE( to->x );
  947.       to_y  = UPSCALE( to->y );
  948.       mid_x = ( ras.x + to_x +
  949.                 3 * UPSCALE( control1->x + control2->x ) ) / 8;
  950.       mid_y = ( ras.y + to_y +
  951.                 3 * UPSCALE( control1->y + control2->y ) ) / 8;
  952.  
  953.       gray_render_line( RAS_VAR_ mid_x, mid_y );
  954.       gray_render_line( RAS_VAR_ to_x, to_y );
  955.       return;
  956.     }
  957.  
  958.     arc      = ras.bez_stack;
  959.     arc[0].x = UPSCALE( to->x );
  960.     arc[0].y = UPSCALE( to->y );
  961.     arc[1].x = UPSCALE( control2->x );
  962.     arc[1].y = UPSCALE( control2->y );
  963.     arc[2].x = UPSCALE( control1->x );
  964.     arc[2].y = UPSCALE( control1->y );
  965.     arc[3].x = ras.x;
  966.     arc[3].y = ras.y;
  967.  
  968.     levels    = ras.lev_stack;
  969.     top       = 0;
  970.     levels[0] = level;
  971.  
  972.     while ( top >= 0 )
  973.     {
  974.       level = levels[top];
  975.       if ( level > 1 )
  976.       {
  977.         /* check that the arc crosses the current band */
  978.         TPos  min, max, y;
  979.  
  980.  
  981.         min = max = arc[0].y;
  982.         y = arc[1].y;
  983.         if ( y < min ) min = y;
  984.         if ( y > max ) max = y;
  985.         y = arc[2].y;
  986.         if ( y < min ) min = y;
  987.         if ( y > max ) max = y;
  988.         y = arc[3].y;
  989.         if ( y < min ) min = y;
  990.         if ( y > max ) max = y;
  991.         if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
  992.           goto Draw;
  993.         gray_split_cubic( arc );
  994.         arc += 3;
  995.         top ++;
  996.         levels[top] = levels[top - 1] = level - 1;
  997.         continue;
  998.       }
  999.  
  1000.     Draw:
  1001.       {
  1002.         TPos  to_x, to_y, mid_x, mid_y;
  1003.  
  1004.  
  1005.         to_x  = arc[0].x;
  1006.         to_y  = arc[0].y;
  1007.         mid_x = ( ras.x + to_x + 3 * ( arc[1].x + arc[2].x ) ) / 8;
  1008.         mid_y = ( ras.y + to_y + 3 * ( arc[1].y + arc[2].y ) ) / 8;
  1009.  
  1010.         gray_render_line( RAS_VAR_ mid_x, mid_y );
  1011.         gray_render_line( RAS_VAR_ to_x, to_y );
  1012.         top --;
  1013.         arc -= 3;
  1014.       }
  1015.     }
  1016.     return;
  1017.   }
  1018.  
  1019.  
  1020.   /* a macro comparing two cell pointers.  Returns true if a <= b. */
  1021. #if 1
  1022.  
  1023. #define PACK( a )          ( ( (long)(a)->y << 16 ) + (a)->x )
  1024. #define LESS_THAN( a, b )  ( PACK( a ) < PACK( b ) )
  1025.  
  1026. #else /* 1 */
  1027.  
  1028. #define LESS_THAN( a, b )  ( (a)->y < (b)->y || \
  1029.                              ( (a)->y == (b)->y && (a)->x < (b)->x ) )
  1030.  
  1031. #endif /* 1 */
  1032.  
  1033. #define SWAP_CELLS( a, b, temp )  do             \
  1034.                                   {              \
  1035.                                     temp = *(a); \
  1036.                                     *(a) = *(b); \
  1037.                                     *(b) = temp; \
  1038.                                   } while ( 0 )
  1039. #define DEBUG_SORT
  1040. #define QUICK_SORT
  1041.  
  1042. #ifdef SHELL_SORT
  1043.  
  1044.   /* a simple shell sort algorithm that works directly on our */
  1045.   /* cells table                                              */
  1046.   static void
  1047.   gray_shell_sort ( PCell  cells,
  1048.                     int    count )
  1049.   {
  1050.     PCell  i, j, limit = cells + count;
  1051.     TCell  temp;
  1052.     int    gap;
  1053.  
  1054.  
  1055.     /* compute initial gap */
  1056.     for ( gap = 0; ++gap < count; gap *= 3 )
  1057.       ;
  1058.  
  1059.     while ( gap /= 3 )
  1060.     {
  1061.       for ( i = cells + gap; i < limit; i++ )
  1062.       {
  1063.         for ( j = i - gap; ; j -= gap )
  1064.         {
  1065.           PCell  k = j + gap;
  1066.  
  1067.  
  1068.           if ( LESS_THAN( j, k ) )
  1069.             break;
  1070.  
  1071.           SWAP_CELLS( j, k, temp );
  1072.  
  1073.           if ( j < cells + gap )
  1074.             break;
  1075.         }
  1076.       }
  1077.     }
  1078.   }
  1079.  
  1080. #endif /* SHELL_SORT */
  1081.  
  1082.  
  1083. #ifdef QUICK_SORT
  1084.  
  1085.   /* This is a non-recursive quicksort that directly process our cells     */
  1086.   /* array.  It should be faster than calling the stdlib qsort(), and we   */
  1087.   /* can even tailor our insertion threshold...                            */
  1088.  
  1089. #define QSORT_THRESHOLD  9  /* below this size, a sub-array will be sorted */
  1090.                             /* through a normal insertion sort             */
  1091.  
  1092.   static void
  1093.   gray_quick_sort( PCell  cells,
  1094.                    int    count )
  1095.   {
  1096.     PCell   stack[40];  /* should be enough ;-) */
  1097.     PCell*  top;        /* top of stack */
  1098.     PCell   base, limit;
  1099.     TCell   temp;
  1100.  
  1101.  
  1102.     limit = cells + count;
  1103.     base  = cells;
  1104.     top   = stack;
  1105.  
  1106.     for (;;)
  1107.     {
  1108.       int    len = (int)( limit - base );
  1109.       PCell  i, j, pivot;
  1110.  
  1111.  
  1112.       if ( len > QSORT_THRESHOLD )
  1113.       {
  1114.         /* we use base + len/2 as the pivot */
  1115.         pivot = base + len / 2;
  1116.         SWAP_CELLS( base, pivot, temp );
  1117.  
  1118.         i = base + 1;
  1119.         j = limit - 1;
  1120.  
  1121.         /* now ensure that *i <= *base <= *j */
  1122.         if ( LESS_THAN( j, i ) )
  1123.           SWAP_CELLS( i, j, temp );
  1124.  
  1125.         if ( LESS_THAN( base, i ) )
  1126.           SWAP_CELLS( base, i, temp );
  1127.  
  1128.         if ( LESS_THAN( j, base ) )
  1129.           SWAP_CELLS( base, j, temp );
  1130.  
  1131.         for (;;)
  1132.         {
  1133.           do i++; while ( LESS_THAN( i, base ) );
  1134.           do j--; while ( LESS_THAN( base, j ) );
  1135.  
  1136.           if ( i > j )
  1137.             break;
  1138.  
  1139.           SWAP_CELLS( i, j, temp );
  1140.         }
  1141.  
  1142.         SWAP_CELLS( base, j, temp );
  1143.  
  1144.         /* now, push the largest sub-array */
  1145.         if ( j - base > limit - i )
  1146.         {
  1147.           top[0] = base;
  1148.           top[1] = j;
  1149.           base   = i;
  1150.         }
  1151.         else
  1152.         {
  1153.           top[0] = i;
  1154.           top[1] = limit;
  1155.           limit  = j;
  1156.         }
  1157.         top += 2;
  1158.       }
  1159.       else
  1160.       {
  1161.         /* the sub-array is small, perform insertion sort */
  1162.         j = base;
  1163.         i = j + 1;
  1164.  
  1165.         for ( ; i < limit; j = i, i++ )
  1166.         {
  1167.           for ( ; LESS_THAN( j + 1, j ); j-- )
  1168.           {
  1169.             SWAP_CELLS( j + 1, j, temp );
  1170.             if ( j == base )
  1171.               break;
  1172.           }
  1173.         }
  1174.         if ( top > stack )
  1175.         {
  1176.           top  -= 2;
  1177.           base  = top[0];
  1178.           limit = top[1];
  1179.         }
  1180.         else
  1181.           break;
  1182.       }
  1183.     }
  1184.   }
  1185.  
  1186. #endif /* QUICK_SORT */
  1187.  
  1188.  
  1189. #ifdef DEBUG_GRAYS
  1190. #ifdef DEBUG_SORT
  1191.  
  1192.   static int
  1193.   gray_check_sort( PCell  cells,
  1194.                    int    count )
  1195.   {
  1196.     PCell  p, q;
  1197.  
  1198.  
  1199.     for ( p = cells + count - 2; p >= cells; p-- )
  1200.     {
  1201.       q = p + 1;
  1202.       if ( !LESS_THAN( p, q ) )
  1203.         return 0;
  1204.     }
  1205.     return 1;
  1206.   }
  1207.  
  1208. #endif /* DEBUG_SORT */
  1209. #endif /* DEBUG_GRAYS */
  1210.  
  1211.  
  1212.   static int
  1213.   gray_move_to( FT_Vector*  to,
  1214.                 FT_Raster   raster )
  1215.   {
  1216.     TPos  x, y;
  1217.  
  1218.  
  1219.     /* record current cell, if any */
  1220.     gray_record_cell( (PRaster)raster );
  1221.  
  1222.     /* start to a new position */
  1223.     x = UPSCALE( to->x );
  1224.     y = UPSCALE( to->y );
  1225.  
  1226.     gray_start_cell( (PRaster)raster, TRUNC( x ), TRUNC( y ) );
  1227.  
  1228.     ((PRaster)raster)->x = x;
  1229.     ((PRaster)raster)->y = y;
  1230.     return 0;
  1231.   }
  1232.  
  1233.  
  1234.   static int
  1235.   gray_line_to( FT_Vector*  to,
  1236.                 FT_Raster   raster )
  1237.   {
  1238.     gray_render_line( (PRaster)raster,
  1239.                       UPSCALE( to->x ), UPSCALE( to->y ) );
  1240.     return 0;
  1241.   }
  1242.  
  1243.  
  1244.   static int
  1245.   gray_conic_to( FT_Vector*  control,
  1246.                  FT_Vector*  to,
  1247.                  FT_Raster   raster )
  1248.   {
  1249.     gray_render_conic( (PRaster)raster, control, to );
  1250.     return 0;
  1251.   }
  1252.  
  1253.  
  1254.   static int
  1255.   gray_cubic_to( FT_Vector*  control1,
  1256.                  FT_Vector*  control2,
  1257.                  FT_Vector*  to,
  1258.                  FT_Raster   raster )
  1259.   {
  1260.     gray_render_cubic( (PRaster)raster, control1, control2, to );
  1261.     return 0;
  1262.   }
  1263.  
  1264.  
  1265.   static void
  1266.   gray_render_span( int       y,
  1267.                     int       count,
  1268.                     FT_Span*  spans,
  1269.                     PRaster   raster )
  1270.   {
  1271.     unsigned char*  p;
  1272.     FT_Bitmap*      map = &raster->target;
  1273.  
  1274.  
  1275.     /* first of all, compute the scanline offset */
  1276.     p = (unsigned char*)map->buffer - y * map->pitch;
  1277.     if ( map->pitch >= 0 )
  1278.       p += ( map->rows - 1 ) * map->pitch;
  1279.  
  1280.     for ( ; count > 0; count--, spans++ )
  1281.     {
  1282.       FT_UInt  coverage = spans->coverage;
  1283.  
  1284.  
  1285. #ifdef GRAYS_USE_GAMMA
  1286.       coverage = raster->gamma[(FT_Byte)coverage];
  1287. #endif
  1288.  
  1289.       if ( coverage )
  1290. #if 1
  1291.         MEM_Set( p + spans->x, (unsigned char)coverage, spans->len );
  1292. #else /* 1 */
  1293.       {
  1294.         q     = p + spans->x;
  1295.         limit = q + spans->len;
  1296.         for ( ; q < limit; q++ )
  1297.           q[0] = (unsigned char)coverage;
  1298.       }
  1299. #endif /* 1 */
  1300.     }
  1301.   }
  1302.  
  1303.  
  1304. #ifdef DEBUG_GRAYS
  1305.  
  1306. #include <stdio.h>
  1307.  
  1308.   static void
  1309.   gray_dump_cells( RAS_ARG )
  1310.   {
  1311.     PCell  cell, limit;
  1312.     int    y = -1;
  1313.  
  1314.  
  1315.     cell  = ras.cells;
  1316.     limit = cell + ras.num_cells;
  1317.  
  1318.     for ( ; cell < limit; cell++ )
  1319.     {
  1320.       if ( cell->y != y )
  1321.       {
  1322.         fprintf( stderr, "\n%2d: ", cell->y );
  1323.         y = cell->y;
  1324.       }
  1325.       fprintf( stderr, "[%d %d %d]",
  1326.                cell->x, cell->area, cell->cover );
  1327.     }
  1328.     fprintf(stderr, "\n" );
  1329.   }
  1330.  
  1331. #endif /* DEBUG_GRAYS */
  1332.  
  1333.  
  1334.   static void
  1335.   gray_hline( RAS_ARG_ TScan  x,
  1336.                        TScan  y,
  1337.                        TPos   area,
  1338.                        int    acount )
  1339.   {
  1340.     FT_Span*   span;
  1341.     int        count;
  1342.     int        coverage;
  1343.  
  1344.  
  1345.     /* compute the coverage line's coverage, depending on the    */
  1346.     /* outline fill rule                                         */
  1347.     /*                                                           */
  1348.     /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */
  1349.     /*                                                           */
  1350.     coverage = area >> ( PIXEL_BITS * 2 + 1 - 8);  /* use range 0..256 */
  1351.  
  1352.     if ( ras.outline.flags & ft_outline_even_odd_fill )
  1353.     {
  1354.       if ( coverage < 0 )
  1355.         coverage = -coverage;
  1356.  
  1357.       while ( coverage >= 512 )
  1358.         coverage -= 512;
  1359.  
  1360.       if ( coverage > 256 )
  1361.         coverage = 512 - coverage;
  1362.       else if ( coverage == 256 )
  1363.         coverage = 255;
  1364.     }
  1365.     else
  1366.     {
  1367.       /* normal non-zero winding rule */
  1368.       if ( coverage < 0 )
  1369.         coverage = -coverage;
  1370.  
  1371.       if ( coverage >= 256 )
  1372.         coverage = 255;
  1373.     }
  1374.  
  1375.     y += ras.min_ey;
  1376.     x += ras.min_ex;
  1377.  
  1378.     if ( coverage )
  1379.     {
  1380.       /* see if we can add this span to the current list */
  1381.       count = ras.num_gray_spans;
  1382.       span  = ras.gray_spans + count - 1;
  1383.       if ( count > 0                          &&
  1384.            ras.span_y == y                    &&
  1385.            (int)span->x + span->len == (int)x &&
  1386.            span->coverage == coverage )
  1387.       {
  1388.         span->len = (unsigned short)( span->len + acount );
  1389.         return;
  1390.       }
  1391.  
  1392.       if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS )
  1393.       {
  1394.         if ( ras.render_span && count > 0 )
  1395.           ras.render_span( ras.span_y, count, ras.gray_spans,
  1396.                            ras.render_span_data );
  1397.         /* ras.render_span( span->y, ras.gray_spans, count ); */
  1398.  
  1399. #ifdef DEBUG_GRAYS
  1400.  
  1401.         if ( ras.span_y >= 0 )
  1402.         {
  1403.           int  n;
  1404.  
  1405.  
  1406.           fprintf( stderr, "y=%3d ", ras.span_y );
  1407.           span = ras.gray_spans;
  1408.           for ( n = 0; n < count; n++, span++ )
  1409.             fprintf( stderr, "[%d..%d]:%02x ",
  1410.                      span->x, span->x + span->len - 1, span->coverage );
  1411.           fprintf( stderr, "\n" );
  1412.         }
  1413.  
  1414. #endif /* DEBUG_GRAYS */
  1415.  
  1416.         ras.num_gray_spans = 0;
  1417.         ras.span_y         = y;
  1418.  
  1419.         count = 0;
  1420.         span  = ras.gray_spans;
  1421.       }
  1422.       else
  1423.         span++;
  1424.  
  1425.       /* add a gray span to the current list */
  1426.       span->x        = (short)x;
  1427.       span->len      = (unsigned short)acount;
  1428.       span->coverage = (unsigned char)coverage;
  1429.       ras.num_gray_spans++;
  1430.     }
  1431.   }
  1432.  
  1433.  
  1434.   static void
  1435.   gray_sweep( RAS_ARG_ FT_Bitmap*  target )
  1436.   {
  1437.     TScan  x, y, cover;
  1438.     TArea  area;
  1439.     PCell  start, cur, limit;
  1440.  
  1441.     FT_UNUSED( target );
  1442.  
  1443.     if ( ras.num_cells == 0 )
  1444.       return;
  1445.  
  1446.     cur   = ras.cells;
  1447.     limit = cur + ras.num_cells;
  1448.  
  1449.     cover              = 0;
  1450.     ras.span_y         = -1;
  1451.     ras.num_gray_spans = 0;
  1452.  
  1453.     for (;;)
  1454.     {
  1455.       start  = cur;
  1456.       y      = start->y;
  1457.       x      = start->x;
  1458.  
  1459.       area   = start->area;
  1460.       cover += start->cover;
  1461.  
  1462.       /* accumulate all start cells */
  1463.       for (;;)
  1464.       {
  1465.         ++cur;
  1466.         if ( cur >= limit || cur->y != start->y || cur->x != start->x )
  1467.           break;
  1468.  
  1469.         area  += cur->area;
  1470.         cover += cur->cover;
  1471.       }
  1472.  
  1473.       /* if the start cell has a non-null area, we must draw an */
  1474.       /* individual gray pixel there                            */
  1475.       if ( area && x >= 0 )
  1476.       {
  1477.         gray_hline( RAS_VAR_ x, y, cover * ( ONE_PIXEL * 2 ) - area, 1 );
  1478.         x++;
  1479.       }
  1480.  
  1481.       if ( x < 0 )
  1482.         x = 0;
  1483.  
  1484.       if ( cur < limit && start->y == cur->y )
  1485.       {
  1486.         /* draw a gray span between the start cell and the current one */
  1487.         if ( cur->x > x )
  1488.           gray_hline( RAS_VAR_ x, y,
  1489.                        cover * ( ONE_PIXEL * 2 ), cur->x - x );
  1490.       }
  1491.       else
  1492.       {
  1493.         /* draw a gray span until the end of the clipping region */
  1494.         if ( cover && x < ras.max_ex - ras.min_ex )
  1495.           gray_hline( RAS_VAR_ x, y,
  1496.                        cover * ( ONE_PIXEL * 2 ),
  1497.                        ras.max_ex - x - ras.min_ex );
  1498.         cover = 0;
  1499.       }
  1500.  
  1501.       if ( cur >= limit )
  1502.         break;
  1503.     }
  1504.  
  1505.     if ( ras.render_span && ras.num_gray_spans > 0 )
  1506.       ras.render_span( ras.span_y, ras.num_gray_spans,
  1507.                        ras.gray_spans, ras.render_span_data );
  1508.  
  1509. #ifdef DEBUG_GRAYS
  1510.  
  1511.     {
  1512.       int       n;
  1513.       FT_Span*  span;
  1514.  
  1515.  
  1516.       fprintf( stderr, "y=%3d ", ras.span_y );
  1517.       span = ras.gray_spans;
  1518.       for ( n = 0; n < ras.num_gray_spans; n++, span++ )
  1519.         fprintf( stderr, "[%d..%d]:%02x ",
  1520.                  span->x, span->x + span->len - 1, span->coverage );
  1521.       fprintf( stderr, "\n" );
  1522.     }
  1523.  
  1524. #endif /* DEBUG_GRAYS */
  1525.  
  1526.   }
  1527.  
  1528.  
  1529. #ifdef _STANDALONE_
  1530.  
  1531.   /*************************************************************************/
  1532.   /*                                                                       */
  1533.   /*  The following function should only compile in stand_alone mode,      */
  1534.   /*  i.e., when building this component without the rest of FreeType.     */
  1535.   /*                                                                       */
  1536.   /*************************************************************************/
  1537.  
  1538.   /*************************************************************************/
  1539.   /*                                                                       */
  1540.   /* <Function>                                                            */
  1541.   /*    FT_Outline_Decompose                                               */
  1542.   /*                                                                       */
  1543.   /* <Description>                                                         */
  1544.   /*    Walks over an outline's structure to decompose it into individual  */
  1545.   /*    segments and Bezier arcs.  This function is also able to emit      */
  1546.   /*    `move to' and `close to' operations to indicate the start and end  */
  1547.   /*    of new contours in the outline.                                    */
  1548.   /*                                                                       */
  1549.   /* <Input>                                                               */
  1550.   /*    outline   :: A pointer to the source target.                       */
  1551.   /*                                                                       */
  1552.   /*    interface :: A table of `emitters', i.e,. function pointers called */
  1553.   /*                 during decomposition to indicate path operations.     */
  1554.   /*                                                                       */
  1555.   /*    user      :: A typeless pointer which is passed to each emitter    */
  1556.   /*                 during the decomposition.  It can be used to store    */
  1557.   /*                 the state during the decomposition.                   */
  1558.   /*                                                                       */
  1559.   /* <Return>                                                              */
  1560.   /*    Error code.  0 means sucess.                                       */
  1561.   /*                                                                       */
  1562.   static
  1563.   int  FT_Outline_Decompose( FT_Outline*              outline,
  1564.                              const FT_Outline_Funcs*  interface,
  1565.                              void*                    user )
  1566.   {
  1567. #undef SCALED
  1568. #if 0
  1569. #define SCALED( x )  ( ( (x) << shift ) - delta )
  1570. #else
  1571. #define SCALED( x )  (x)
  1572. #endif
  1573.  
  1574.     FT_Vector   v_last;
  1575.     FT_Vector   v_control;
  1576.     FT_Vector   v_start;
  1577.  
  1578.     FT_Vector*  point;
  1579.     FT_Vector*  limit;
  1580.     char*       tags;
  1581.  
  1582.     int     n;         /* index of contour in outline     */
  1583.     int     first;     /* index of first point in contour */
  1584.     int     error;
  1585.     char    tag;       /* current point's state           */
  1586.  
  1587. #if 0
  1588.     int     shift = interface->shift;
  1589.     FT_Pos  delta = interface->delta;
  1590. #endif
  1591.  
  1592.  
  1593.     first = 0;
  1594.  
  1595.     for ( n = 0; n < outline->n_contours; n++ )
  1596.     {
  1597.       int  last;  /* index of last point in contour */
  1598.  
  1599.  
  1600.       last  = outline->contours[n];
  1601.       limit = outline->points + last;
  1602.  
  1603.       v_start = outline->points[first];
  1604.       v_last  = outline->points[last];
  1605.  
  1606.       v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y );
  1607.       v_last.x  = SCALED( v_last.x );  v_last.y  = SCALED( v_last.y );
  1608.  
  1609.       v_control = v_start;
  1610.  
  1611.       point = outline->points + first;
  1612.       tags  = outline->tags  + first;
  1613.       tag   = FT_CURVE_TAG( tags[0] );
  1614.  
  1615.       /* A contour cannot start with a cubic control point! */
  1616.       if ( tag == FT_Curve_Tag_Cubic )
  1617.         goto Invalid_Outline;
  1618.  
  1619.       /* check first point to determine origin */
  1620.       if ( tag == FT_Curve_Tag_Conic )
  1621.       {
  1622.         /* first point is conic control.  Yes, this happens. */
  1623.         if ( FT_CURVE_TAG( outline->tags[last] ) == FT_Curve_Tag_On )
  1624.         {
  1625.           /* start at last point if it is on the curve */
  1626.           v_start = v_last;
  1627.           limit--;
  1628.         }
  1629.         else
  1630.         {
  1631.           /* if both first and last points are conic,         */
  1632.           /* start at their middle and record its position    */
  1633.           /* for closure                                      */
  1634.           v_start.x = ( v_start.x + v_last.x ) / 2;
  1635.           v_start.y = ( v_start.y + v_last.y ) / 2;
  1636.  
  1637.           v_last = v_start;
  1638.         }
  1639.         point--;
  1640.         tags--;
  1641.       }
  1642.  
  1643.       error = interface->move_to( &v_start, user );
  1644.       if ( error )
  1645.         goto Exit;
  1646.  
  1647.       while ( point < limit )
  1648.       {
  1649.         point++;
  1650.         tags++;
  1651.  
  1652.         tag = FT_CURVE_TAG( tags[0] );
  1653.         switch ( tag )
  1654.         {
  1655.         case FT_Curve_Tag_On:  /* emit a single line_to */
  1656.           {
  1657.             FT_Vector  vec;
  1658.  
  1659.  
  1660.             vec.x = SCALED( point->x );
  1661.             vec.y = SCALED( point->y );
  1662.  
  1663.             error = interface->line_to( &vec, user );
  1664.             if ( error )
  1665.               goto Exit;
  1666.             continue;
  1667.           }
  1668.  
  1669.         case FT_Curve_Tag_Conic:  /* consume conic arcs */
  1670.           {
  1671.             v_control.x = SCALED( point->x );
  1672.             v_control.y = SCALED( point->y );
  1673.  
  1674.           Do_Conic:
  1675.             if ( point < limit )
  1676.             {
  1677.               FT_Vector  vec;
  1678.               FT_Vector  v_middle;
  1679.  
  1680.  
  1681.               point++;
  1682.               tags++;
  1683.               tag = FT_CURVE_TAG( tags[0] );
  1684.  
  1685.               vec.x = SCALED( point->x );
  1686.               vec.y = SCALED( point->y );
  1687.  
  1688.               if ( tag == FT_Curve_Tag_On )
  1689.               {
  1690.                 error = interface->conic_to( &v_control, &vec, user );
  1691.                 if ( error )
  1692.                   goto Exit;
  1693.                 continue;
  1694.               }
  1695.  
  1696.               if ( tag != FT_Curve_Tag_Conic )
  1697.                 goto Invalid_Outline;
  1698.  
  1699.               v_middle.x = ( v_control.x + vec.x ) / 2;
  1700.               v_middle.y = ( v_control.y + vec.y ) / 2;
  1701.  
  1702.               error = interface->conic_to( &v_control, &v_middle, user );
  1703.               if ( error )
  1704.                 goto Exit;
  1705.  
  1706.               v_control = vec;
  1707.               goto Do_Conic;
  1708.             }
  1709.  
  1710.             error = interface->conic_to( &v_control, &v_start, user );
  1711.             goto Close;
  1712.           }
  1713.  
  1714.         default:  /* FT_Curve_Tag_Cubic */
  1715.           {
  1716.             FT_Vector  vec1, vec2;
  1717.  
  1718.  
  1719.             if ( point + 1 > limit                             ||
  1720.                  FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic )
  1721.               goto Invalid_Outline;
  1722.  
  1723.             point += 2;
  1724.             tags  += 2;
  1725.  
  1726.             vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y );
  1727.             vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y );
  1728.  
  1729.             if ( point <= limit )
  1730.             {
  1731.               FT_Vector  vec;
  1732.  
  1733.  
  1734.               vec.x = SCALED( point->x );
  1735.               vec.y = SCALED( point->y );
  1736.  
  1737.               error = interface->cubic_to( &vec1, &vec2, &vec, user );
  1738.               if ( error )
  1739.                 goto Exit;
  1740.               continue;
  1741.             }
  1742.  
  1743.             error = interface->cubic_to( &vec1, &vec2, &v_start, user );
  1744.             goto Close;
  1745.           }
  1746.         }
  1747.       }
  1748.  
  1749.       /* close the contour with a line segment */
  1750.       error = interface->line_to( &v_start, user );
  1751.  
  1752.    Close:
  1753.       if ( error )
  1754.         goto Exit;
  1755.  
  1756.       first = last + 1;
  1757.     }
  1758.  
  1759.     return 0;
  1760.  
  1761.   Exit:
  1762.     return error;
  1763.  
  1764.   Invalid_Outline:
  1765.     return ErrRaster_Invalid_Outline;
  1766.   }
  1767.  
  1768. #endif /* _STANDALONE_ */
  1769.  
  1770.  
  1771.   typedef struct  TBand_
  1772.   {
  1773.     FT_Pos  min, max;
  1774.  
  1775.   } TBand;
  1776.  
  1777.  
  1778.   static int
  1779.   gray_convert_glyph_inner( RAS_ARG )
  1780.   {
  1781.     static
  1782.     const FT_Outline_Funcs  interface =
  1783.     {
  1784.       (FT_Outline_MoveTo_Func) gray_move_to,
  1785.       (FT_Outline_LineTo_Func) gray_line_to,
  1786.       (FT_Outline_ConicTo_Func)gray_conic_to,
  1787.       (FT_Outline_CubicTo_Func)gray_cubic_to,
  1788.       0,
  1789.       0
  1790.     };
  1791.  
  1792.     volatile int  error = 0;
  1793.  
  1794.     if ( setjmp( ras.jump_buffer ) == 0 )
  1795.     {
  1796.       error = FT_Outline_Decompose( &ras.outline, &interface, &ras );
  1797.       gray_record_cell( RAS_VAR );
  1798.     }
  1799.     else
  1800.     {
  1801.       error = ErrRaster_MemoryOverflow;
  1802.     }
  1803.  
  1804.     return error;
  1805.   }
  1806.  
  1807.  
  1808.   static int
  1809.   gray_convert_glyph( RAS_ARG )
  1810.   {
  1811.     TBand             bands[40];
  1812.     volatile  TBand*  band;
  1813.     volatile  int     n, num_bands;
  1814.     volatile  TPos    min, max, max_y;
  1815.     FT_BBox*          clip;
  1816.  
  1817.  
  1818.     /* Set up state in the raster object */
  1819.     gray_compute_cbox( RAS_VAR );
  1820.  
  1821.     /* clip to target bitmap, exit if nothing to do */
  1822.     clip = &ras.clip_box;
  1823.  
  1824.     if ( ras.max_ex <= clip->xMin || ras.min_ex >= clip->xMax ||
  1825.          ras.max_ey <= clip->yMin || ras.min_ey >= clip->yMax )
  1826.       return 0;
  1827.  
  1828.     if ( ras.min_ex < clip->xMin ) ras.min_ex = clip->xMin;
  1829.     if ( ras.min_ey < clip->yMin ) ras.min_ey = clip->yMin;
  1830.  
  1831.     if ( ras.max_ex > clip->xMax ) ras.max_ex = clip->xMax;
  1832.     if ( ras.max_ey > clip->yMax ) ras.max_ey = clip->yMax;
  1833.  
  1834.     /* simple heuristic used to speed-up the bezier decomposition -- see */
  1835.     /* the code in gray_render_conic() and gray_render_cubic() for more  */
  1836.     /* details                                                           */
  1837.     ras.conic_level = 32;
  1838.     ras.cubic_level = 16;
  1839.  
  1840.     {
  1841.       int level = 0;
  1842.  
  1843.  
  1844.       if ( ras.max_ex > 24 || ras.max_ey > 24 )
  1845.         level++;
  1846.       if ( ras.max_ex > 120 || ras.max_ey > 120 )
  1847.         level++;
  1848.  
  1849.       ras.conic_level <<= level;
  1850.       ras.cubic_level <<= level;
  1851.     }
  1852.  
  1853.     /* setup vertical bands */
  1854.     num_bands = ( ras.max_ey - ras.min_ey ) / ras.band_size;
  1855.     if ( num_bands == 0 )  num_bands = 1;
  1856.     if ( num_bands >= 39 ) num_bands = 39;
  1857.  
  1858.     ras.band_shoot = 0;
  1859.  
  1860.     min   = ras.min_ey;
  1861.     max_y = ras.max_ey;
  1862.  
  1863.     for ( n = 0; n < num_bands; n++, min = max )
  1864.     {
  1865.       max = min + ras.band_size;
  1866.       if ( n == num_bands - 1 || max > max_y )
  1867.         max = max_y;
  1868.  
  1869.       bands[0].min = min;
  1870.       bands[0].max = max;
  1871.       band         = bands;
  1872.  
  1873.       while ( band >= bands )
  1874.       {
  1875.         FT_Pos  bottom, top, middle;
  1876.         int     error;
  1877.  
  1878.  
  1879.         ras.num_cells = 0;
  1880.         ras.invalid   = 1;
  1881.         ras.min_ey    = band->min;
  1882.         ras.max_ey    = band->max;
  1883.  
  1884. #if 1
  1885.         error = gray_convert_glyph_inner( RAS_VAR );
  1886. #else
  1887.         error = FT_Outline_Decompose( outline, &interface, &ras ) ||
  1888.                 gray_record_cell( RAS_VAR );
  1889. #endif
  1890.  
  1891.         if ( !error )
  1892.         {
  1893. #ifdef SHELL_SORT
  1894.           gray_shell_sort( ras.cells, ras.num_cells );
  1895. #else
  1896.           gray_quick_sort( ras.cells, ras.num_cells );
  1897. #endif
  1898.  
  1899. #ifdef DEBUG_GRAYS
  1900.           gray_check_sort( ras.cells, ras.num_cells );
  1901.           gray_dump_cells( RAS_VAR );
  1902. #endif
  1903.  
  1904.           gray_sweep( RAS_VAR_  &ras.target );
  1905.           band--;
  1906.           continue;
  1907.         }
  1908.         else if ( error != ErrRaster_MemoryOverflow )
  1909.           return 1;
  1910.  
  1911.         /* render pool overflow, we will reduce the render band by half */
  1912.         bottom = band->min;
  1913.         top    = band->max;
  1914.         middle = bottom + ( ( top - bottom ) >> 1 );
  1915.  
  1916.         /* waoow! This is too complex for a single scanline, something */
  1917.         /* must be really rotten here!                                 */
  1918.         if ( middle == bottom )
  1919.         {
  1920. #ifdef DEBUG_GRAYS
  1921.           fprintf( stderr, "Rotten glyph!\n" );
  1922. #endif
  1923.           return 1;
  1924.         }
  1925.  
  1926.         if ( bottom-top >= ras.band_size )
  1927.           ras.band_shoot++;
  1928.  
  1929.         band[1].min = bottom;
  1930.         band[1].max = middle;
  1931.         band[0].min = middle;
  1932.         band[0].max = top;
  1933.         band++;
  1934.       }
  1935.     }
  1936.  
  1937.     if ( ras.band_shoot > 8 && ras.band_size > 16 )
  1938.       ras.band_size = ras.band_size / 2;
  1939.  
  1940.     return 0;
  1941.   }
  1942.  
  1943.  
  1944.   extern int
  1945.   gray_raster_render( PRaster            raster,
  1946.                       FT_Raster_Params*  params )
  1947.   {
  1948.     FT_Outline*  outline = (FT_Outline*)params->source;
  1949.     FT_Bitmap*   target_map = params->target;
  1950.  
  1951.  
  1952.     if ( !raster || !raster->cells || !raster->max_cells )
  1953.       return -1;
  1954.  
  1955.     /* return immediately if the outline is empty */
  1956.     if ( outline->n_points == 0 || outline->n_contours <= 0 )
  1957.       return 0;
  1958.  
  1959.     if ( !outline || !outline->contours || !outline->points )
  1960.       return ErrRaster_Invalid_Outline;
  1961.  
  1962.     if ( outline->n_points !=
  1963.            outline->contours[outline->n_contours - 1] + 1 )
  1964.       return ErrRaster_Invalid_Outline;
  1965.  
  1966.     /* if direct mode is not set, we must have a target bitmap */
  1967.     if ( ( params->flags & ft_raster_flag_direct ) == 0 &&
  1968.          ( !target_map || !target_map->buffer )         )
  1969.       return -1;
  1970.  
  1971.     /* this version does not support monochrome rendering */
  1972.     if ( !( params->flags & ft_raster_flag_aa ) )
  1973.       return ErrRaster_Invalid_Mode;
  1974.  
  1975.     /* compute clipping box */
  1976.     if ( ( params->flags & ft_raster_flag_direct ) == 0 )
  1977.     {
  1978.       /* compute clip box from target pixmap */
  1979.       ras.clip_box.xMin = 0;
  1980.       ras.clip_box.yMin = 0;
  1981.       ras.clip_box.xMax = target_map->width;
  1982.       ras.clip_box.yMax = target_map->rows;
  1983.     }
  1984.     else if ( params->flags & ft_raster_flag_clip )
  1985.     {
  1986.       ras.clip_box = params->clip_box;
  1987.     }
  1988.     else
  1989.     {
  1990.       ras.clip_box.xMin = -32768L;
  1991.       ras.clip_box.yMin = -32768L;
  1992.       ras.clip_box.xMax =  32767L;
  1993.       ras.clip_box.yMax =  32767L;
  1994.     }
  1995.  
  1996.     ras.outline   = *outline;
  1997.     ras.num_cells = 0;
  1998.     ras.invalid   = 1;
  1999.  
  2000.     if ( target_map )
  2001.       ras.target = *target_map;
  2002.  
  2003.     ras.render_span      = (FT_Raster_Span_Func)gray_render_span;
  2004.     ras.render_span_data = &ras;
  2005.  
  2006.     if ( params->flags & ft_raster_flag_direct )
  2007.     {
  2008.       ras.render_span      = (FT_Raster_Span_Func)params->gray_spans;
  2009.       ras.render_span_data = params->user;
  2010.     }
  2011.  
  2012.     return gray_convert_glyph( (PRaster)raster );
  2013.   }
  2014.  
  2015.  
  2016.   /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
  2017.   /****                         a static object.                  *****/
  2018.  
  2019. #ifdef GRAYS_USE_GAMMA
  2020.  
  2021.   /* initialize the "gamma" table. Yes, this is really a crummy function */
  2022.   /* but the results look pretty good for something that simple.         */
  2023.   /*                                                                     */
  2024. #define M_MAX  255
  2025. #define M_X    128
  2026. #define M_Y    192
  2027.  
  2028.   static void
  2029.   grays_init_gamma( PRaster  raster )
  2030.   {
  2031.     FT_UInt  x, a;
  2032.  
  2033.  
  2034.     for ( x = 0; x < 256; x++ )
  2035.     {
  2036.       if ( x <= M_X )
  2037.         a = ( x * M_Y + M_X / 2) / M_X;
  2038.       else
  2039.         a = M_Y + ( ( x - M_X ) * ( M_MAX - M_Y ) +
  2040.             ( M_MAX - M_X ) / 2 ) / ( M_MAX - M_X );
  2041.  
  2042.       raster->gamma[x] = (FT_Byte)a;
  2043.     }
  2044.   }
  2045.  
  2046. #endif /* GRAYS_USE_GAMMA */
  2047.  
  2048. #ifdef _STANDALONE_
  2049.  
  2050.   static int
  2051.   gray_raster_new( void*       memory,
  2052.                    FT_Raster*  araster )
  2053.   {
  2054.     static TRaster  the_raster;
  2055.  
  2056.     FT_UNUSED( memory );
  2057.  
  2058.  
  2059.     *araster = (FT_Raster)&the_raster;
  2060.     MEM_Set( &the_raster, 0, sizeof ( the_raster ) );
  2061.  
  2062. #ifdef GRAYS_USE_GAMMA
  2063.     grays_init_gamma( (PRaster)*araster );
  2064. #endif
  2065.  
  2066.     return 0;
  2067.   }
  2068.  
  2069.  
  2070.   static void
  2071.   gray_raster_done( FT_Raster  raster )
  2072.   {
  2073.     /* nothing */
  2074.     FT_UNUSED( raster );
  2075.   }
  2076.  
  2077. #else /* _STANDALONE_ */
  2078.  
  2079.   static int
  2080.   gray_raster_new( FT_Memory   memory,
  2081.                    FT_Raster*  araster )
  2082.   {
  2083.     FT_Error  error;
  2084.     PRaster   raster;
  2085.  
  2086.  
  2087.     *araster = 0;
  2088.     if ( !ALLOC( raster, sizeof ( TRaster ) ) )
  2089.     {
  2090.       raster->memory = memory;
  2091.       *araster = (FT_Raster)raster;
  2092.  
  2093. #ifdef GRAYS_USE_GAMMA
  2094.       grays_init_gamma( raster );
  2095. #endif
  2096.     }
  2097.  
  2098.     return error;
  2099.   }
  2100.  
  2101.  
  2102.   static void
  2103.   gray_raster_done( FT_Raster  raster )
  2104.   {
  2105.     FT_Memory  memory = (FT_Memory)((PRaster)raster)->memory;
  2106.  
  2107.  
  2108.     FREE( raster );
  2109.   }
  2110.  
  2111. #endif /* _STANDALONE_ */
  2112.  
  2113.  
  2114.   static void
  2115.   gray_raster_reset( FT_Raster    raster,
  2116.                      const char*  pool_base,
  2117.                      long         pool_size )
  2118.   {
  2119.     PRaster  rast = (PRaster)raster;
  2120.  
  2121.  
  2122.     if ( raster && pool_base && pool_size >= 4096 )
  2123.       gray_init_cells( rast, (char*)pool_base, pool_size );
  2124.  
  2125.     rast->band_size  = ( pool_size / sizeof ( TCell ) ) / 8;
  2126.   }
  2127.  
  2128.  
  2129.   const FT_Raster_Funcs  ft_grays_raster =
  2130.   {
  2131.     ft_glyph_format_outline,
  2132.  
  2133.     (FT_Raster_New_Func)      gray_raster_new,
  2134.     (FT_Raster_Reset_Func)    gray_raster_reset,
  2135.     (FT_Raster_Set_Mode_Func) 0,
  2136.     (FT_Raster_Render_Func)   gray_raster_render,
  2137.     (FT_Raster_Done_Func)     gray_raster_done
  2138.   };
  2139.  
  2140.  
  2141. /* END */
  2142.